package assingment.cortica.artem.barger;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

/**
 * 
 * Reads configuration file to setup working properties.
 * Capable of downloading images files using sized thread pool.
 * 
 * <b>Assumed we managing only jpg file format, for assignment only</b>
 * 
 * @author Artem Barger 
 *
 */
public class DownloadersManager extends Thread {

	private static final String DOWNLOADERS_THREAD_POOL_SIZE = "downloaders.thread.pool.size";

	private static final String DOWNLOADERS_IMAGE_QUEUE_FOLDER = "downloaders.image.queue.folder";

	private Logger log = Logger.getLogger( DownloadersManager.class);
	
	private ExecutorService threadPool;
	
	private String imagesQueueFolder;

	private volatile boolean shutdown = false;

	public DownloadersManager( ) {
		Properties properties = new	Properties( );
		try {
			// Load property file.
			properties.load( DownloadersManager.class.getClassLoader().getResourceAsStream( "cortica.properties"));
			imagesQueueFolder = properties.getProperty( DOWNLOADERS_IMAGE_QUEUE_FOLDER, "queue");
			int poolSize = Integer.valueOf( properties.getProperty( DOWNLOADERS_THREAD_POOL_SIZE, "5"));
			threadPool = Executors.newFixedThreadPool( poolSize);
		} catch (IOException e) {
			log.error( e);
		}
	}
	
	@Override
	public void run( ) {
		File queueFolder = new File( imagesQueueFolder);
		if ( !queueFolder.isDirectory( )) {
			throw new RuntimeException( "Queue folder is not a directory!");
		}
		while (!shutdown) {
			// List files in the queue directory
			File[] files = getImagesFilesList(queueFolder);
			if ( files.length == 0) {
				try {
					Thread.sleep( 500);
				} catch (InterruptedException e) {
					log.error( e);
				}
				continue;
			}
			for ( File file : files) {
				if ( !file.exists()) 
					continue;
				log.info( "Parsing file:" + file.getName( ) + "...");
				// Parse files to get list of images to download and resize.
				readImagesToDownload(file);
				file.delete( );
				if ( shutdown)
					break;
			}
		}
		// Once finished need shutdown thread pool object.
		threadPool.shutdown( );
		//Wait until all tasks has been finished
		while ( !threadPool.isShutdown( )) {
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				log.error( e);
			}
		}
	}

	public void shutdown( ) {
		this.shutdown = true;
	}
	
	private void readImagesToDownload(File file) {
		BufferedReader reader = null;
		try {
			reader = new BufferedReader( new FileReader(file));
			String line = null;
			while ( ( line = reader.readLine( )) != null && !shutdown) {
				log.info( "Downloading image from URL: " + line + ".");
				threadPool.execute( new Downloader( new URL( line)));
			}
		} catch (Exception e) {
			log.error( e);
		} finally {
			StreamUtils.closeReader(reader);
		}
	}

	/**
	 * Filters queue files list. 
	 * @param queueFolder
	 * @return return only files with .lst extension.
	 */
	private File[] getImagesFilesList(File queueFolder) {
		File[] files = queueFolder.listFiles( new FileFilter() {
			@Override
			public boolean accept(File pathname) {
				return pathname.isFile() && pathname.getName().toLowerCase( ).matches( "[A-Za-z0-9]*.lst");
			}
		});
		return files;
	}
	
	public static void main(String... args) {
		DownloadersManager manager = new DownloadersManager( );
		manager.start( );
		BufferedReader reader = new BufferedReader( new InputStreamReader( System.in));
		try {
			while( (reader.readLine( )).equalsIgnoreCase( "exit")) { }
		} catch (IOException e) {
			e.printStackTrace();
		}
		manager.shutdown( );
	}
}